﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace MN.Framework.Common
{
    [Serializable]
    public class LogicalValidationRule : ValidationRule
    {
        // Fields
        private string basePropertyName;
        private string customMessageInsteadofValue;
        private LogicalOperator logicalOperator;

        // Methods
        public LogicalValidationRule(LogicalOperator logicalOperator, string propertyName)
            : this(logicalOperator, propertyName, "")
        {
        }

        public LogicalValidationRule(LogicalOperator logicalOperator, string propertyName, string customMessageInsteadofValue)
        {
            this.logicalOperator = logicalOperator;
            this.basePropertyName = propertyName;
            this.customMessageInsteadofValue = customMessageInsteadofValue;
        }

        //public LogicalValidationRule(LogicalOperator logicalOperator, string propertyName, Type entityType, string entityColumnName)
        //    : this(logicalOperator, propertyName)
        //{
        //    EntityPropertyNameConcept concept2 = new EntityPropertyNameConcept
        //    {
        //        ComponentName = FrameworkHelper.GetComponentNameFromAssembly(entityType.Assembly),
        //        EntityName = entityType.Name,
        //        PropertyName = entityColumnName
        //    };
        //    this.customMessageInsteadofValue = concept2.TranslateOrDefault();
        //}

        public override bool IsValid(BaseEntity record, string propertyName)
        {
            string LogicalOperatorTitle = " -- ";
            bool flag = false;
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new MnException("Property name cant be null");
            }
            PropertyInfo property = record.PropertyByName(propertyName);
            if (property == null)
            {
                throw new MnException("Property {0} on entity of type {1} not found", new object[] { propertyName, record.GetType().Name });
            }
            if (string.IsNullOrEmpty(this.basePropertyName))
            {
                throw new MnException("Base property name on entity of type {0} cant be null", new object[] { record.GetType().Name });
            }
            PropertyInfo info2 = record.PropertyByName(this.basePropertyName);
            if (info2 == null)
            {
                throw new MnException("Base property {0} on entity of type {1} not found", new object[] { this.basePropertyName, record.GetType().Name });
            }
            if (!property.PropertyType.IsAssignableFrom(info2.PropertyType))
            {
                throw new MnException("Property {0} on entity of type {1} isn't assignable to property {2}", new object[] { propertyName, record.GetType().Name, this.basePropertyName });
            }
            object valueFast = info2.GetValueFast(record);
            bool flag2 = property.GetValueFast(record) == null;
            if (!(flag2 || (property.GetValueFast(record) is IComparable)))
            {
                throw new MnException("Property type {0} of property {1} on entity {2} isn't comparable", new object[] { property.PropertyType, propertyName, record.GetType().Name, this.basePropertyName });
            }
            int num = 0;
            if (!((valueFast == null) || flag2))
            {
                num = ((IComparable)record.PropertyByName(propertyName).GetValueFast(record)).CompareTo(valueFast);
            }
            switch (this.logicalOperator)
            {
                case LogicalOperator.Equal:
                    flag = num == 0;
                    if (flag2 && (valueFast == null))
                        flag = true;
                    if (!flag)
                        LogicalOperatorTitle = "برابر با ";
                    break;

                case LogicalOperator.GreaterThan:
                    flag = num > 0;
                    if (flag2 || (valueFast == null))
                        flag = false;
                    if (!flag)
                        LogicalOperatorTitle = "بیشتر از ";
                    break;

                case LogicalOperator.GreaterThanOrEqual:
                    flag = num >= 0;
                    if (flag2 || (valueFast == null))
                        flag = false;
                    if (!flag)
                        LogicalOperatorTitle = "بیشتر یا مساوی با ";
                    break;

                case LogicalOperator.LessThan:
                    flag = num < 0;
                    if (flag2 || (valueFast == null))
                        flag = false;

                    if (!flag)
                        LogicalOperatorTitle = "کمتر از ";
                    break;

                case LogicalOperator.LessThanOrEqual:
                    flag = num <= 0;
                    if (flag2 || (valueFast == null))
                        flag = false;

                    if (!flag)
                        LogicalOperatorTitle = "کمتر یا مساوی با  ";
                    break;

                case LogicalOperator.NotEqual:
                    flag = num != 0;
                    if ((flag2 && (valueFast != null)) || (!flag2 && (valueFast == null)))                    
                        flag = true;
                    if (!flag)
                        LogicalOperatorTitle = " نامساوی با  ";
                    break;
            }
            if (!flag)
            {
                List<ColumnInfo> columns = new List<ColumnInfo>();
                record.GetColumns(columns);
                var BasePropertyHeader = columns.Find(c => c.Name == basePropertyName).HeaderText;
                var mainPropertyheader = columns.Find(c => c.Name == propertyName).HeaderText;
                base.ErrorMessage = string.Format(Resource.CommonCore.InvalidLogicalOperationValue, mainPropertyheader, LogicalOperatorTitle, BasePropertyHeader);
            }
            return flag;
        }
    }

}
